namespace Maple.Branch.Identity.DataSeed
{
    using System;
    using System.Threading.Tasks;
    using Base.Consts;
    using Configurations;
    using Entities;
    using Extensions;
    using IRepositories;
    using Microsoft.AspNetCore.Identity;
    using Services;
    using Volo.Abp;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Guids;
    using Volo.Abp.Uow;

    public class IdentityDataSeeder : ITransientDependency, IIdentityDataSeeder
    {
        public IdentityDataSeeder(
            IGuidGenerator guidGenerator,
            IIdentityRoleRepository roleRepository,
            IIdentityUserRepository userRepository,
            ILookupNormalizer lookupNormalizer,
            IdentityUserManager userManager,
            IdentityRoleManager roleManager,
            IRootConfiguration rootConfiguration)
        {
            GuidGenerator = guidGenerator;
            RoleRepository = roleRepository;
            UserRepository = userRepository;
            LookupNormalizer = lookupNormalizer;
            UserManager = userManager;
            RoleManager = roleManager;
            RootConfiguration = rootConfiguration;
        }

        #region protected

        protected IGuidGenerator GuidGenerator { get; }

        protected IIdentityRoleRepository RoleRepository { get; }

        protected IIdentityUserRepository UserRepository { get; }

        protected ILookupNormalizer LookupNormalizer { get; }

        protected IdentityUserManager UserManager { get; }

        protected IdentityRoleManager RoleManager { get; }

        protected IRootConfiguration RootConfiguration { get; }

        #endregion

        [UnitOfWork]
        public virtual async Task<IdentityDataSeedResult> CreateAdminAsync(
            string adminEmail,
            string adminPassword,
            Guid? tenantId = null)
        {
            Check.NotNullOrWhiteSpace(adminEmail, nameof(adminEmail));
            Check.NotNullOrWhiteSpace(adminPassword, nameof(adminPassword));

            var result = new IdentityDataSeedResult();

            //"admin" user
            var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
                LookupNormalizer.NormalizeName(BranchConsts.Admin.UserName)
            );

            if (adminUser != null)
            {
                return result;
            }

            adminUser = new IdentityUser(
                GuidGenerator.Create(),
                BranchConsts.Admin.UserName,
                adminEmail,
                tenantId
            )
            {
                Name = RootConfiguration.Admin.Name,
            };

            (await UserManager.CreateAsync(adminUser, adminPassword)).CheckErrors();

            result.CreatedAdminUser = true;

            //"admin" role
            var adminRole = await RoleRepository.FindByNormalizedNameAsync(
                LookupNormalizer.NormalizeName(BranchConsts.Admin.RoleName));

            if (adminRole == null)
            {
                adminRole = new IdentityRole(
                    GuidGenerator.Create(),
                    BranchConsts.Admin.RoleName,
                    tenantId
                )
                {
                    IsStatic = true,
                    IsPublic = true
                };

                (await RoleManager.CreateAsync(adminRole)).CheckErrors();

                result.CreatedAdminRole = true;
            }

            (await UserManager.AddToRoleAsync(adminUser, BranchConsts.Admin.RoleName)).CheckErrors();

            return result;
        }
    }
}
